package com.jfeat.am.module.wegou.api.patch;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.jfeat.am.common.constant.tips.ErrorTip;
import com.jfeat.am.common.constant.tips.SuccessTip;
import com.jfeat.am.common.constant.tips.Tip;
import com.jfeat.am.common.controller.BaseController;
import com.jfeat.am.common.crud.CRUD;
import com.jfeat.am.core.jwt.JWTService;
import com.jfeat.am.module.wegou.constant.IdentityEnum;
import com.jfeat.am.module.wegou.exception.WegouBizException;
import com.jfeat.am.module.wegou.kit.RestClient;
import com.jfeat.am.module.wegou.services.crud.service.ProductStoreService;
import com.jfeat.am.module.wegou.services.crud.service.UserIdentityService;
import com.jfeat.am.module.wegou.services.domain.model.LoginModel;
import com.jfeat.am.module.wegou.services.domain.model.RegisterModel;
import com.jfeat.am.module.wegou.services.patch.UserIdentityPatchService;
import com.jfeat.am.module.wegou.services.persistence.model.ProductStore;
import com.jfeat.am.module.wegou.services.persistence.model.UserIdentity;
import com.jfinal.kit.StrKit;
import io.jsonwebtoken.Claims;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.HttpStatusCodeException;

import javax.annotation.Resource;

/**
 * Created by Administrator on 2018/1/31.
 */
@Api(value = "公用的后台用户Oauth")
@RestController
@RequestMapping("/api/pub/wegou/oauth")
public class WegouPubOauthEndpoint extends BaseController {

    @Resource
    ProductStoreService productStoreService;
    @Resource
    UserIdentityService userIdentityService;
    @Resource
    UserIdentityPatchService userIdentityPatchService;

    RestClient rest = new RestClient();

    @Value("${server.port}")
    private String port;

    @ApiOperation(value = "平台/料理店铺/商户店铺 登录API")
    @PostMapping("/login")
    public Tip login(@RequestBody LoginModel loginModel) {
        if (StrKit.isBlank(loginModel.getIdentity())) {
            return ErrorTip.create(WegouBizException.LOGIN_IDENTITY_REQUIRED.getCode(),
                    WegouBizException.LOGIN_IDENTITY_REQUIRED.getMessage());
        }
        //必须是 平台用户/料理店铺/商户店铺 ，其他身份不符
        if (!(loginModel.getIdentity().equals(IdentityEnum.PLATFORM.toString()) ||
                !loginModel.getIdentity().equals(IdentityEnum.RESTAURANT.toString()) ||
                !loginModel.getIdentity().equals(IdentityEnum.CANTEEN.toString()))) {
            return ErrorTip.create(WegouBizException.LOGIN_IDENTITY_NOT_MATCH.getCode(),
                    WegouBizException.LOGIN_IDENTITY_NOT_MATCH.getMessage());
        }

        ResponseEntity<String> responseEntity = null;
        try {
            //捕获诸如密码错误等会抛出的500错误
            responseEntity = doLogin(loginModel);
        } catch (Exception e) {
            return ErrorTip.create(5000, "登录失败");
        }

        int code = getCode(responseEntity);
        if (!(code == HttpStatus.OK.value())) {
            return ErrorTip.create(code, getMessage(responseEntity));
        }
        JSONObject data = getData(responseEntity);
        Long userId = getUserId(data);

        //检查用户身份（首先必须在UserIdentity表有相应记录）
        if (!userIdentityPatchService.isIdentity(userId, loginModel.getIdentity())) {
            return ErrorTip.create(WegouBizException.LOGIN_IDENTITY_NOT_MATCH.getCode(),
                    WegouBizException.LOGIN_IDENTITY_NOT_MATCH.getMessage());
        }
        if (loginModel.getIdentity().equals(IdentityEnum.RESTAURANT.toString())) {
            //其次，如果是以料理店铺的身份登录，则必须找到与该用户对应的ProductRestaurant
            ProductStore productRestaurant = productStoreService.findFirstByUserId(userId);  //一个用户只能有一家料理店铺
            if (productRestaurant == null) {
                return ErrorTip.create(WegouBizException.NOT_RESTAURANT_OR_CANTEEN.getCode(),
                        WegouBizException.NOT_RESTAURANT_OR_CANTEEN.getMessage());
            }
            if (productRestaurant.getLocked().equals(1)) {
                return ErrorTip.create(WegouBizException.SHOP_LOCKED.getCode(),
                        WegouBizException.SHOP_LOCKED.getMessage());
            }
        }

        return SuccessTip.create(data);
    }

//    *********************
    private ResponseEntity<String> doRegister(RegisterModel model) {
        String api = "http://127.0.0.1:" + port + "/api/oauth/register";
        HttpEntity<RegisterModel> requestEntity = new HttpEntity<RegisterModel>(model, rest.getHeaders());
        ResponseEntity<String> responseEntity = rest.exchange(api, HttpMethod.POST, requestEntity, String.class);
        return responseEntity;
    }

    @ApiOperation(value = "商店 料理店 注册 API")
    @PostMapping("/register")
    public Tip register(@RequestBody RegisterModel model) {
        //validate
        if (StrKit.isBlank(model.getIdentity())) {
            return ErrorTip.create(WegouBizException.IDENTITY_IS_REQUIRED.getCode(), WegouBizException.IDENTITY_IS_REQUIRED.getMessage());
        }

        // 暂时只有料理店 当为料理店的时候，才插入操作
        if (IdentityEnum.RESTAURANT.toString().equals(model.getIdentity()) || IdentityEnum.CANTEEN.toString().equals(model.getIdentity())) {
            ResponseEntity<String> responseEntity = null;
            try {
                responseEntity = doRegister(model);
            } catch (HttpStatusCodeException e) {
                logger.error(e.getResponseBodyAsString());
                return ErrorTip.create(5001, "注册失败");
            }

            int code = getCode(responseEntity);
            if (!(code == HttpStatus.OK.value())) {
                return ErrorTip.create(code, getMessage(responseEntity));
            }

            //登录以获得userId
            LoginModel loginModel = new LoginModel();
            JSONObject from = CRUD.toJSONObject(model);
            JSONObject to = CRUD.toJSONObject(loginModel);
            CRUD.copyFrom(to, from, true);
            loginModel = CRUD.castObject(to, LoginModel.class);

            ResponseEntity<String> loginResponseEntity = null;
            try {
                //捕获诸如密码错误等会抛出的500错误
                loginResponseEntity = doLogin(loginModel);
            } catch (Exception e) {
                return ErrorTip.create(5000, "登录失败");
            }
            JSONObject loginData = getData(loginResponseEntity);
            Long userId = getUserId(loginData);


            // 插入 料理店数据
            ProductStore restaurant = new ProductStore();
            restaurant.setUserId(userId);
            restaurant.setSortNumber(1);
            restaurant.setStatus(RestaurantStatus.RISE.toString());
            restaurant.setStoreType("RESTAURANT");
            productStoreService.createMaster(restaurant);

            //插入身份信息
            UserIdentity userIdentity = new UserIdentity();
            userIdentity.setIdentity(model.getIdentity());
            userIdentity.setUserId(userId);
            userIdentity.setNote("料理店铺");
            return SuccessTip.create(userIdentityService.createMaster(userIdentity));

        } else if (IdentityEnum.CANTEEN.toString().equals(model.getIdentity())) {
            //TODO 二期加上 商户店铺
            ResponseEntity<String> responseEntity = null;
            try {
                responseEntity = doRegister(model);
            } catch (Exception e) {
                return ErrorTip.create(5001, "注册失败");
            }

            int code = getCode(responseEntity);
            if (!(code == HttpStatus.OK.value())) {
                return ErrorTip.create(code, getMessage(responseEntity));
            }

            //登录以获得userId
            LoginModel loginModel = new LoginModel();
            JSONObject from = CRUD.toJSONObject(model);
            JSONObject to = CRUD.toJSONObject(loginModel);
            CRUD.copyFrom(to, from, true);
            loginModel = CRUD.castObject(to, LoginModel.class);

            ResponseEntity<String> loginResponseEntity = null;
            try {
                //捕获诸如密码错误等会抛出的500错误
                loginResponseEntity = doLogin(loginModel);
            } catch (Exception e) {
                return ErrorTip.create(5000, "登录失败");
            }
            JSONObject loginData = getData(loginResponseEntity);
            Long userId = getUserId(loginData);


            // 插入 商户店铺数据
            ProductStore restaurant = new ProductStore();
            restaurant.setUserId(userId);
            restaurant.setSortNumber(1);
            restaurant.setStatus(RestaurantStatus.RISE.toString());
            restaurant.setStoreType("CANTEEN");
            productStoreService.createMaster(restaurant);

            //插入身份信息
            UserIdentity userIdentity = new UserIdentity();
            userIdentity.setIdentity(model.getIdentity());
            userIdentity.setUserId(userId);
            userIdentity.setNote("商户店铺");
            return SuccessTip.create(userIdentityService.createMaster(userIdentity));
        }
        return ErrorTip.create(WegouBizException.REGISTER_FAILURE.getCode(), WegouBizException.REGISTER_FAILURE.getMessage());
    }

    private ResponseEntity<String> doLogin(LoginModel loginModel) {
        String api = "http://127.0.0.1:" + port + "/api/oauth/login";
        HttpEntity<LoginModel> requestEntity = new HttpEntity<LoginModel>(loginModel, rest.getHeaders());
        ResponseEntity<String> responseEntity = rest.exchange(api, HttpMethod.POST, requestEntity, String.class);
        return responseEntity;
    }

    private int getCode(ResponseEntity<String> responseEntity) {
        String response = responseEntity.getBody();
        JSONObject jsonObject = JSON.parseObject(response);
        return jsonObject.getIntValue("code");
    }

    private String getMessage(ResponseEntity<String> responseEntity) {
        String response = responseEntity.getBody();
        JSONObject jsonObject = JSON.parseObject(response);
        return jsonObject.getString("message");
    }

    private JSONObject getData(ResponseEntity<String> responseEntity) {
        String response = responseEntity.getBody();
        JSONObject jsonObject = JSON.parseObject(response);
        return jsonObject.getJSONObject("data");
    }

    private Long getUserId(JSONObject data) {
        Claims claims = JWTService.me().parseToken(data.getString("accessToken"));
        return Long.parseLong((String) claims.get("userId"));
    }

}
